/**
 * 数字模块 - 借鉴各种数字处理库的设计理念
 * 提供数字验证、格式化、计算等功能
 */

// 数字相关正则表达式
const NUMBER_PATTERNS = {
  integer: /^-?\d+$/,
  float: /^-?\d+\.?\d*$/,
  positiveNumber: /^[0-9]+\.?[0-9]*$/,
  percentage: /^\d+(\.\d+)?%$/
};

/**
 * 判断是否为数字（通过Number转换）
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为数字
 */
export function isNumber(value) {
  if (value === null || value === undefined) return false;
  if (typeof value === 'boolean') return false;
  if (typeof value === 'string' && value.trim() === '') return false;

  const num = Number(value);
  return !isNaN(num) && isFinite(num);
}

/**
 * 用正则判断是否为数字
 * @param {string} str 要检查的字符串
 * @returns {boolean} 是否为数字
 */
export function isNumberByRegex(str) {
  if (typeof str !== 'string') return false;
  return NUMBER_PATTERNS.positiveNumber.test(str);
}

/**
 * 判断是否为整数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为整数
 */
export function isInteger(value) {
  if (typeof value !== 'number') return false;
  return Number.isInteger(value);
}

/**
 * 判断是否为浮点数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为浮点数
 */
export function isFloat(value) {
  if (typeof value !== 'number') return false;
  return !Number.isInteger(value) && isFinite(value);
}

/**
 * 判断是否为正数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为正数
 */
export function isPositive(value) {
  if (!isNumber(value)) return false;
  return Number(value) > 0;
}

/**
 * 判断是否为负数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为负数
 */
export function isNegative(value) {
  if (!isNumber(value)) return false;
  return Number(value) < 0;
}

/**
 * 判断是否在指定范围内
 * @param {number} value 要检查的值
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns {boolean} 是否在范围内
 */
export function inRange(value, min, max) {
  if (!isNumber(value)) return false;
  const num = Number(value);
  return num >= min && num <= max;
}

/**
 * 限制数字在指定范围内
 * @param {number} value 数字
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns {number} 限制后的数字
 */
export function clamp(value, min, max) {
  if (!isNumber(value)) return min;
  const num = Number(value);
  return Math.min(Math.max(num, min), max);
}

/**
 * 格式化金额（千分位格式）
 * @param {number} money 金额
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的金额
 */
export function formatMoney(money, precision = 2) {
  if (!isNumber(money)) return '0.00';

  return Number(money).toLocaleString('zh-CN', {
    minimumFractionDigits: precision,
    maximumFractionDigits: precision
  });
}

/**
 * 格式化数字（添加千分位分隔符）
 * @param {number} num 数字
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的数字
 */
export function formatNumber(num, precision = 2) {
  if (!isNumber(num)) return '0';

  const number = Number(num).toFixed(precision);
  const parts = number.split('.');

  // 添加千分位分隔符
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');

  return parts.join('.');
}

/**
 * 格式化文件大小
 * @param {number} bytes 字节数
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的文件大小
 */
export function formatFileSize(bytes, precision = 2) {
  if (!isNumber(bytes)) return '0 B';

  const num = Number(bytes);
  if (num === 0) return '0 B';

  const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
  const index = Math.floor(Math.log(Math.abs(num)) / Math.log(1024));
  const size = num / Math.pow(1024, index);

  return size.toFixed(precision) + ' ' + units[index];
}

/**
 * 格式化百分比
 * @param {number} num 数字（0-1）
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的百分比
 */
export function formatPercentage(num, precision = 2) {
  if (!isNumber(num)) return '0%';

  return (Number(num) * 100).toFixed(precision) + '%';
}

/**
 * 解析百分比字符串
 * @param {string} str 百分比字符串
 * @returns {number} 数字（0-1）
 */
export function parsePercentage(str) {
  if (typeof str !== 'string') return 0;
  if (!NUMBER_PATTERNS.percentage.test(str)) return 0;

  return parseFloat(str.replace('%', '')) / 100;
}

/**
 * 随机整数（包含边界）
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns {number} 随机整数
 */
export function randomInt(min = 0, max = 100) {
  if (!isNumber(min) || !isNumber(max)) return 0;

  const minNum = Math.ceil(Number(min));
  const maxNum = Math.floor(Number(max));

  return Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum;
}

/**
 * 随机浮点数
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @param {number} precision 小数位数
 * @returns {number} 随机浮点数
 */
export function randomFloat(min = 0, max = 1, precision = 2) {
  if (!isNumber(min) || !isNumber(max)) return 0;

  const minNum = Number(min);
  const maxNum = Number(max);
  const random = Math.random() * (maxNum - minNum) + minNum;

  return Number(random.toFixed(precision));
}

/**
 * 加法运算（解决浮点数精度问题）
 * @param {...number} numbers 数字
 * @returns {number} 和
 */
export function add(...numbers) {
  if (numbers.length === 0) return 0;
  if (numbers.length === 1) return isNumber(numbers[0]) ? Number(numbers[0]) : 0;

  let result = 0;
  let maxDecimal = 0;

  // 找到最大小数位数
  for (const num of numbers) {
    if (!isNumber(num)) continue;
    const decimal = (Number(num).toString().split('.')[1] || '').length;
    maxDecimal = Math.max(maxDecimal, decimal);
  }

  const multiplier = Math.pow(10, maxDecimal);

  // 累加计算
  for (const num of numbers) {
    if (isNumber(num)) {
      result += Number(num) * multiplier;
    }
  }

  return result / multiplier;
}

/**
 * 减法运算（解决浮点数精度问题）
 * @param {number} a 数字a
 * @param {number} b 数字b
 * @returns {number} 差
 */
export function subtract(a, b) {
  if (!isNumber(a) || !isNumber(b)) return 0;

  const numA = Number(a);
  const numB = Number(b);

  const decimalA = (numA.toString().split('.')[1] || '').length;
  const decimalB = (numB.toString().split('.')[1] || '').length;
  const maxDecimal = Math.max(decimalA, decimalB);

  const multiplier = Math.pow(10, maxDecimal);

  return (numA * multiplier - numB * multiplier) / multiplier;
}

/**
 * 乘法运算（解决浮点数精度问题）
 * @param {...number} numbers 数字
 * @returns {number} 积
 */
export function multiply(...numbers) {
  if (numbers.length === 0) return 0;
  if (numbers.length === 1) return isNumber(numbers[0]) ? Number(numbers[0]) : 0;

  let totalDecimal = 0;

  // 计算总小数位数
  for (const num of numbers) {
    if (!isNumber(num)) return 0;
    const decimal = (Number(num).toString().split('.')[1] || '').length;
    totalDecimal += decimal;
  }

  const multiplier = Math.pow(10, totalDecimal);
  let integerResult = 1;

  // 转换为整数相乘
  for (const num of numbers) {
    const numValue = Number(num);
    const decimal = (numValue.toString().split('.')[1] || '').length;
    const integerValue = Math.round(numValue * Math.pow(10, decimal));
    integerResult *= integerValue;
  }

  return integerResult / multiplier;
}

/**
 * 除法运算（解决浮点数精度问题）
 * @param {number} a 数字a
 * @param {number} b 数字b
 * @returns {number} 商
 */
export function divide(a, b) {
  if (!isNumber(a) || !isNumber(b)) return 0;

  const numA = Number(a);
  const numB = Number(b);

  if (numB === 0) return numA > 0 ? Infinity : numA < 0 ? -Infinity : NaN;

  const decimalA = (numA.toString().split('.')[1] || '').length;
  const decimalB = (numB.toString().split('.')[1] || '').length;

  const multiplier = Math.pow(10, Math.max(decimalA, decimalB));

  return (numA * multiplier) / (numB * multiplier);
}

/**
 * 四舍五入到指定小数位
 * @param {number} num 数字
 * @param {number} precision 小数位数
 * @returns {number} 四舍五入后的数字
 */
export function round(num, precision = 0) {
  if (!isNumber(num)) return 0;

  const multiplier = Math.pow(10, precision);
  return Math.round(Number(num) * multiplier) / multiplier;
}

/**
 * 向上取整到指定小数位
 * @param {number} num 数字
 * @param {number} precision 小数位数
 * @returns {number} 向上取整后的数字
 */
export function ceil(num, precision = 0) {
  if (!isNumber(num)) return 0;

  const multiplier = Math.pow(10, precision);
  return Math.ceil(Number(num) * multiplier) / multiplier;
}

/**
 * 向下取整到指定小数位
 * @param {number} num 数字
 * @param {number} precision 小数位数
 * @returns {number} 向下取整后的数字
 */
export function floor(num, precision = 0) {
  if (!isNumber(num)) return 0;

  const multiplier = Math.pow(10, precision);
  return Math.floor(Number(num) * multiplier) / multiplier;
}

/**
 * 数字转中文（内部辅助函数，用于万以下数字）
 * @param {number} num 数字
 * @returns {string} 中文数字
 */
function _toChinese(num) {
  if (!isNumber(num)) return '零';

  const number = Math.abs(Math.floor(Number(num)));
  if (number === 0) return '零';

  const digits = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  const units = ['', '十', '百', '千'];

  const str = number.toString();
  let result = '';

  for (let i = 0; i < str.length; i++) {
    const digit = parseInt(str[i], 10);
    const unitIndex = str.length - i - 1;

    if (digit !== 0) {
      // 对于千位到个位的处理
      if (unitIndex < units.length) {
        result += digits[digit] + units[unitIndex];
      }
    } else if (result && !result.endsWith('零') && i < str.length - 1) {
      // 中间的零需要保留
      result += '零';
    }
  }

  // 清理连续的零和结尾的零
  result = result.replace(/零+/g, '零');
  result = result.replace(/零$/, '');

  // 处理"一十"的特殊情况
  if (result.startsWith('一十')) {
    result = result.replace('一十', '十');
  }

  return result;
}

/**
 * 生成等差数列
 * @param {number} start 起始值
 * @param {number} end 结束值
 * @param {number} step 步长
 * @returns {number[]} 等差数列数组
 */
export function range(start, end, step = 1) {
  if (!isNumber(start) || !isNumber(end) || !isNumber(step)) return [];
  if (step === 0) return [];

  const result = [];
  const startNum = Number(start);
  const endNum = Number(end);
  const stepNum = Number(step);

  if (stepNum > 0) {
    for (let i = startNum; i < endNum; i += stepNum) {
      result.push(i);
    }
  } else {
    for (let i = startNum; i > endNum; i += stepNum) {
      result.push(i);
    }
  }

  return result;
}

/**
 * 计算最大公约数
 * @param {number} a 数字a
 * @param {number} b 数字b
 * @returns {number} 最大公约数
 */
export function gcd(a, b) {
  if (!isInteger(a) || !isInteger(b)) return 1;

  let numA = Math.abs(Number(a));
  let numB = Math.abs(Number(b));

  while (numB !== 0) {
    const temp = numB;
    numB = numA % numB;
    numA = temp;
  }

  return numA;
}

/**
 * 计算最小公倍数
 * @param {number} a 数字a
 * @param {number} b 数字b
 * @returns {number} 最小公倍数
 */
export function lcm(a, b) {
  if (!isInteger(a) || !isInteger(b)) return 0;

  const numA = Math.abs(Number(a));
  const numB = Math.abs(Number(b));

  return (numA * numB) / gcd(numA, numB);
}

/**
 * 生成随机数
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @param {boolean} integer 是否返回整数
 * @returns {number} 随机数
 */
export function random(min = 0, max = 1, integer = false) {
  if (!isNumber(min) || !isNumber(max)) return 0;

  const minNum = Number(min);
  const maxNum = Number(max);

  if (minNum > maxNum) {
    return random(maxNum, minNum, integer);
  }

  const randomValue = Math.random() * (maxNum - minNum) + minNum;

  if (integer) {
    return Math.floor(randomValue);
  }

  return randomValue;
}

/**
 * 格式化货币
 * @param {number} num 数字
 * @param {string} symbol 货币符号
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的货币
 */
export function formatCurrency(num, symbol = '¥', precision = 2) {
  if (!isNumber(num)) return symbol + '0';

  const number = Number(num).toFixed(precision);
  const parts = number.split('.');

  // 添加千分位分隔符
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');

  return symbol + parts.join('.');
}

/**
 * 格式化百分比
 * @param {number} num 数字
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的百分比
 */
export function formatPercent(num, precision = 2) {
  if (!isNumber(num)) return '0%';

  return (Number(num) * 100).toFixed(precision) + '%';
}

/**
 * 万亿单位简化格式化（原formatMoney功能，现改名为formatMoneySimple）
 * @param {number} money 金额
 * @param {number} precision 小数位数
 * @returns {string} 格式化后的金额
 */
export function formatMoneySimple(money, precision = 2) {
  if (!isNumber(money)) return '0';

  const num = Number(money);
  if (num >= 100000000) { // 1亿
    return (num / 100000000).toFixed(precision) + '亿';
  } else if (num >= 10000) { // 1万
    return (num / 10000).toFixed(precision) + '万';
  } else {
    return num.toFixed(precision);
  }
}

/**
 * 中文货币格式化
 * @param {number} amount 金额
 * @returns {string} 中文货币表示
 */
export function formatMoneyToChinese(amount) {
  if (!isNumber(amount)) return '';
  return numberToChinese(amount) + '元';
}

/**
 * 数字转中文（完全重写的版本）
 * @param {number} num 数字
 * @returns {string} 中文数字表示
 */
export function numberToChinese(num) {
  if (!isNumber(num)) return '零';

  const number = Number(num);
  if (number === 0) return '零';

  const isNegative = number < 0;
  const absNum = Math.abs(Math.floor(number));

  const digits = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  const units = ['', '十', '百', '千'];

  // 转换四位数以内的数字
  function convertSection(section) {
    if (section === 0) return '';
    if (section < 10) return digits[section];

    let result = '';
    const str = section.toString().padStart(4, '0');

    for (let i = 0; i < 4; i++) {
      const digit = parseInt(str[i], 10);
      const unitIndex = 3 - i;

      if (digit !== 0) {
        // 特殊处理：十位为1时，省略"一"
        if (unitIndex === 1 && digit === 1 && result === '') {
          result += units[unitIndex];
        } else {
          result += digits[digit] + units[unitIndex];
        }
      } else if (result && !result.endsWith('零') && i < 3) {
        // 添加零（但不在末尾）
        const nextNonZero = str.slice(i + 1).split('').some(d => d !== '0');
        if (nextNonZero) {
          result += '零';
        }
      }
    }

    return result;
  }

  let result = '';

  // 按亿、万、个分段处理
  const yi = Math.floor(absNum / 100000000);      // 亿位部分
  const wan = Math.floor((absNum % 100000000) / 10000);  // 万位部分
  const ge = absNum % 10000;                      // 个位部分

  // 处理亿位
  if (yi > 0) {
    result += convertSection(yi) + '亿';
  }

  // 处理万位
  if (wan > 0) {
    // 如果有亿位且万位小于1000，需要加零
    if (result && wan < 1000) {
      result += '零';
    }
    result += convertSection(wan) + '万';
  }

  // 处理个位
  if (ge > 0) {
    // 如果有万位且个位小于1000，需要加零
    if (result && ge < 1000) {
      result += '零';
    }
    result += convertSection(ge);
  }

  // 处理空结果（输入为0的情况已在开头处理）
  if (!result) {
    result = '零';
  }

  return isNegative ? '负' + result : result;
}

/**
 * 格式化中文数字（保持兼容性）
 * @param {number} num 数字
 * @returns {string} 中文数字表示
 */
export function formatChinese(num) {
  return numberToChinese(num);
}

